#include<stdio.h>
#include<stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <time.h>
#include <pthread.h>
#include <getopt.h>
#include <libgen.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

#include"iniparser.h"
#include"dictionary.h"
#include"cJSON.h"
#include"zlog.h"


#define   ARRAY_SIZE(x)  (sizeof(x)/sizeof(x[0]))

int iniparser_getport(char* conf_file,int* port);
int parser_json(char *buf, char *id, int idsize, float *tmp);
int socket_server_init(char *listen_ip, int listen_port);
static inline void msleep(unsigned long ms);

int main(int argc, char **argv)
{
	int                listenfd,connfd;
	int                serv_port = 0;
	char*              conf_file =NULL;
	int                daemon_run =0;
	char* 		   progname = NULL;
	int                opt;
	fd_set             rdset;
	int                rv;
	int                i,j;
	int                found;
	int                maxfd = 0;
	char               buf[1024];
	int                fds_array[1024];
	float              tmp;
	char	           id[16];

    zlog_category_t *zg =NULL;
	char            *file_zlog = "./server_zlog.conf";
	zlog_init(file_zlog);
	zg = zlog_get_category("server_debug");
	if (!zg)
	{
		printf("zlog_get_category false\n");
		return -2;
	}
                  
    iniparser_getport(conf_file,&serv_port);
	if (!serv_port)
	{
		zlog_debug(zg, "get serv_port error,zlog_debug");
		return -1;
	}
	
    if ((listenfd = socket_server_init(NULL, serv_port)) < 0)
	{
    //	printf("ERROR:%s server lisnten on port %d failure\n",argv[0],serv_port);
        zlog_debug(zg, "server lisnten on port failure, zlog_debug");
		return -2;
	}
	printf("server start to listen on port %d\n" ,serv_port);
    zlog_info(zg,"server start to listen on port,zlog_info");
	if (daemon_run)
	{
		daemon(0, 0); 
	}

	for(i=0;i<ARRAY_SIZE(fds_array);i++)
	{
		fds_array[i] = -1;
	}
	fds_array[0] = listenfd;

	for( ; ; )
	{
		FD_ZERO(&rdset);
		for(i=0; i<ARRAY_SIZE(fds_array); i++)
		{
			if (fds_array[i] < 0)

				continue;

			maxfd = fds_array[i]>maxfd ? fds_array[i] : maxfd;
			FD_SET(fds_array[i],&rdset);
		}        

		rv = select(maxfd+1, &rdset, NULL, NULL, NULL);
		if (rv < 0)
		{
			printf("select failure :%s\n",strerror(errno));
            zlog_debug(zg, "select failure,zlog_debug");
			break;
		}
		else if(rv == 0)
		{
			printf("select get timeout\n");
            zlog_debug(zg, "select get timeout,zlog_debug");
			continue;
		}
		if (FD_ISSET(listenfd, &rdset))
		{
			if ((connfd = accept(listenfd, (struct sockaddr *)NULL,NULL)) < 0)
			{
				printf("accept new client failure :%s\n",strerror(errno));
                zlog_debug(zg, "accept new client failure,zlog_debug");
				continue;
			}
			found = 0;
			for(i=1; i<ARRAY_SIZE(fds_array); i++)
			{
				if (fds_array[i] < 0)  
				{
				//	printf("accept new client [%d] and add it into array\n",connfd);
					fds_array[i] = connfd;
					found = 1;
					break;
				}        

			}
			if (!found)
			{
				printf("accept new client[%d] but full,so refuse it\n",connfd);
                zlog_debug(zg, "accept new client but full,so refuse it,zlog_debug");
				close(connfd);
			}
		}
		else
		{
			for(i=1; i<ARRAY_SIZE(fds_array); i++) 
			{
				if ( fds_array[i] < 0 || !FD_ISSET(fds_array[i],&rdset))
					continue;
				memset(buf, 0, sizeof(buf));
				if ( (rv = read(fds_array[i], buf,sizeof(buf))) <= 0)
				{
					close(fds_array[i]);
					fds_array[i] = -1;
				} 
				else 
				{    
                    printf("buf:%s\n",buf);
                    parser_json(buf, id, sizeof(id), &tmp);
                }
            }
        }

    } 
//  }

    zlog_fini();
CleanUP:
   
	close(listenfd);
	return 0;
}

int iniparser_getport(char* conf_file,int* port)
{
	conf_file = "./client_server.ini";
	dictionary*     dic = NULL;

	dic = iniparser_load("./client_server.ini");
	*port = iniparser_getint(dic,"address:port",0);
	
	return 0;

}
int parser_json(char *buf, char *id, int idsize, float *tmp)
{

	cJSON                 *root;
	cJSON                 *item;
	
	root = cJSON_Parse(buf);/*注意大小写"Pp"*/
	
	if(!buf || !id || !tmp)
	{
		printf("Invalid input arguments\n");
		return -1;

	}
	
	item = cJSON_GetObjectItem(root,"id");
     //	strncpy(id,item->valuestring,idsize);
      	printf("id:%s\n",item->valuestring);

        item = cJSON_GetObjectItem(root,"temperature");
    //  *tmp = item->valuedouble;
    	printf("temperature:%f\n",item->valuedouble);
	
//	item = cJSON_GetObjectItem(root,"get_time");
	//strncpy(get_time,item->valuestring,timesize);
//	printf("get_time:%s\n",item->valuestring);
	cJSON_Delete(root);


}

static inline void msleep(unsigned long ms)
{
	struct timeval tv;

	tv.tv_sec  =  ms/1000;
	tv.tv_usec =  (ms%1000)*1000;

	select(0, NULL, NULL, NULL, &tv);
}


int socket_server_init(char *listen_ip, int listen_port)
{
	struct  sockaddr_in        servaddr;
	int                        rv = 0;
	int                        on = 0;
	int                        listenfd;

	if ( (listenfd = socket(AF_INET,SOCK_STREAM,0)) <0 )
	{ 
		printf("Use socket () to create a TCP socket failure :%s\n",strerror(errno));      
		return -1;
	}
	setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR,&on, sizeof(on)); 
 
	memset(&servaddr, 0, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(listen_port);

	if (!listen_ip) 
	{
		servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	}
	else
	{
		if (inet_pton(AF_INET, listen_ip, &servaddr.sin_addr) <= 0)
		{
			printf("inet_pton() set listen IP address failure\n");   
			rv = -2;       
			goto CleanUp;

		}
	}

	if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
	{
		printf("Use bind() to bind the TCP socket failure:%s\n",strerror(errno));
		rv = -3;
		goto   CleanUp;
	}

	if (listen(listenfd, 13) < 0)
	{
		printf("Use bind() to bind the TCP socket failure:%s\n",strerror(errno));
		rv = -4;
		goto  CleanUp;
	}

CleanUp:
	if (rv < 0)
		close(listenfd);
	else
		rv = listenfd; 

	return rv;


}  






